"
" some advance feature
"

if has('gui_running')
    set guioptions-=r
    set guioptions-=R
    set guioptions-=l
    set guioptions-=L
    set guioptions-=T
    set guioptions-=e
    set noerrorbells
    set novisualbell
    set visualbell t_vb=
endif

set undodir=expand($vimroot/tmp/undo)
set undofile

" set viminfo=%,<800,'10,/50,:100,h,f0,n$vimroot/tmp/viminfo
"           | |    |   |   |    | |  + viminfo file path
"           | |    |   |   |    | + file marks 0-9,A-Z 0=NOT stored
"           | |    |   |   |    + disable 'hlsearch' loading viminfo
"           | |    |   |   + command-line history saved
"           | |    |   + search history saved
"           | |    + files marks saved
"           | + lines saved each register (old name for <, vi6.2)
"           + save/restore buffer list

if system('tmux show-environment THEME')[0:10] == 'THEME=light'
    set background=light
else
    set background=dark
endif

" colorscheme acme
if exists('$vim_simple') 
    " colorscheme off
    colorscheme simple
    set nocursorline
else
    colorscheme peaksea
    set cursorline
endif

set tabline=%!CustomizedTabLine()

command! -nargs=0 -bang VimMetaInit call s:MetaMode(<bang>0)

" TODO - replace the a.vim plugin
noremap <silent><space>fh :call Open_HeaderFile(1)<cr>

nnoremap <silent> <space>wt :call ToggleWindowHorizontalVerticalSplit()<cr>
nnoremap * :keepjumps normal! mi*`i<CR>

" for vim flavor
map  <up>    <nop>
map  <down>  <nop>
map  <left>  <nop>
map  <right> <nop>
imap <up>    <nop>
imap <down>  <nop>
imap <left>  <nop>
imap <right> <nop>

cabbrev ack Ack
cabbrev man Man
cabbrev lf Leaderf
cabbrev clap Clap
cabbrev git Git
cabbrev rg Leaderf rg
cabbrev run AsyncRun
" cabbrev vm Voom markdown
iab xdate <c-r>=strftime("%d/%m/%y %H:%M:%S")<cr>

"
" function
"
function! CustomizedTabLine()
    let s = ''
    let t = tabpagenr()
    let i = 1
    while i <= tabpagenr('$')
        let buflist = tabpagebuflist(i)
        let winnr = tabpagewinnr(i)
        let s .= '%' . i . 'T'
        let s .= (i == t ? '%1*' : '%2*')
        let s .= ' '
        let s .= i . ':'
        let s .= '%*'
        let s .= (i == t ? '%#TabLineSel#' : '%#TabLine#')
        let file = bufname(buflist[winnr - 1])
        let file = fnamemodify(file, ':p:t')
        if file == ''
            let file = '[No Name]'
        endif
        let s .= file
        let s .= ' '
        let i = i + 1
    endwhile
    let s .= '%T%#TabLineFill#%='
    let s .= (tabpagenr('$') > 1 ? '%999XX' : 'X')
    return s
endfunction

function! s:MetaMode(mode)
    set ttimeout
    if $TMUX != ''
        set ttimeoutlen=30
    elseif &ttimeoutlen > 80 || &ttimeoutlen <= 0
        set ttimeoutlen=80
    endif
    if has('nvim') || has('gui_running')
        return
    endif
    function! s:metacode(mode, key)
        if a:mode == 0
            exec "set <M-".a:key.">=\e".a:key
        else
            exec "set <M-".a:key.">=\e]{0}".a:key."~"
        endif
    endfunc
    for i in range(10)
        call s:metacode(a:mode, nr2char(char2nr('0') + i))
    endfor
    for i in range(26)
        call s:metacode(a:mode, nr2char(char2nr('a') + i))
        call s:metacode(a:mode, nr2char(char2nr('A') + i))
    endfor
    if a:mode != 0
        for c in [',', '.', '/', ';', '[', ']', '{', '}']
            call s:metacode(a:mode, c)
        endfor
        for c in ['?', ':', '-', '_', '+', '=']
            call s:metacode(a:mode, c)
        endfor
    else
        for c in [',', '.', '/', ';', '{', '}']
            call s:metacode(a:mode, c)
        endfor
        for c in ['?', ':', '-', '_', '+', '=', "'"]
            call s:metacode(a:mode, c)
        endfor
    endif
endfunc

call s:MetaMode(0)

" toggle buffer full screan
function! HeightToSize(height)
    let currwinno=winnr()
    if winheight(currwinno)>a:height
        while winheight(currwinno)>a:height
            execute "normal \<c-w>-"
        endwhile
    elseif winheight(currwinno)<a:height
        while winheight(currwinno)<a:height
            execute "normal \<c-w>+"
        endwhile
    endif
endfunction

function! WidthToSize(width)
    let currwinno=winnr()
    if winwidth(currwinno)>a:width
        while winwidth(currwinno)>a:width
            execute "normal \<c-w><"
        endwhile

    elseif winwidth(currwinno)<a:width
        while winwidth(currwinno)<a:width
            execute "normal \<c-w>>"
        endwhile
    endif
endfunction

function! TweakWinSize(orgisize)
    call HeightToSize(a:orgisize[0])
    call WidthToSize(a:orgisize[1])
endfunction

function! RestoreWinLayout()
    if exists("g:layout")
        let winno=1
        let orgiwinno=winnr()
        for win in g:layout
            execute "normal \<c-w>w"
            let currwinno=winnr()
            if currwinno!=1 && currwinno!=orgiwinno
                call TweakWinSize(g:layout[currwinno-1])
            endif
        endfor
        unlet g:layout
    endif
endfunction

function! SaveWinLayout()
    let wnumber=winnr("$")
    let winlist=range(wnumber)
    let winno=0
    let layout=[]
    for index in winlist
        let winno+=1
        let wininfo=[winheight(winno),winwidth(winno)]
        call add(layout,wininfo)
    endfor
    let g:layout=layout
endfunction

function! ToggleMaxWin()
    if exists("g:layout")
        if winnr("$")==len(g:layout)
            call RestoreWinLayout()
        else
            call SaveWinLayout()
            execute "normal 200\<c-w>>"
            execute "normal \<c-w>_"
            call RestoreWinLayout()
        endif
    else
        call SaveWinLayout()
        execute "normal 200\<c-w>>"
        execute "normal \<c-w>_"
    endif
endfunction

" open quickfix
function! Toggle_QuickFix(size)
    function! s:WindowCheck(mode)
        if getbufvar('%', '&buftype') == 'quickfix'
            let s:quickfix_open = 1
            return
        endif
        if a:mode == 0
            let w:quickfix_save = winsaveview()
        else
            call winrestview(w:quickfix_save)
        endif
    endfunc

    let s:quickfix_open = 0
    let l:winnr = winnr()
    windo call s:WindowCheck(0)
    if s:quickfix_open == 0
        exec 'botright copen '.a:size
        wincmd k
    else
        cclose
    endif
    windo call s:WindowCheck(1)
    silent exec ''.l:winnr.'wincmd w'
endfunc


" switch header
function! Open_HeaderFile(where)
    let l:main = expand('%:p:r')
    let l:fext = expand('%:e')
    if index(['c', 'cpp', 'm', 'mm', 'cc'], l:fext) >= 0
        let l:altnames = ['h', 'hpp', 'hh']
    elseif index(['h', 'hh', 'hpp'], l:fext) >= 0
        let l:altnames = ['c', 'cpp', 'cc', 'm', 'mm']
    else
        echo 'switch failed, not a c/c++ source'
        return
    endif
    for l:next in l:altnames
        let l:newname = l:main . '.' . l:next
        if filereadable(l:newname)
            if a:where == 0
                call Tools_FileSwitch('e', l:newname)
            elseif a:where == 1
                call Tools_FileSwitch('vs', l:newname)
            else
                call Tools_FileSwitch('tabnew', l:newname)
            endif
            return
        endif
    endfor
    echo 'switch failed, can not find another part of c/c++ source'
endfunc

function! ToggleWindowHorizontalVerticalSplit()
  if !exists('t:splitType')
    let t:splitType = 'vertical'
  endif

  if t:splitType == 'vertical' " is vertical switch to horizontal
    windo wincmd K
    let t:splitType = 'horizontal'

  else " is horizontal switch to vertical
    windo wincmd H
    let t:splitType = 'vertical'
  endif
endfunction

" TODO - Increment a selection of numbers
function! Incr()
    let a = line('.') - line("'<")
    let c = virtcol("'<")
    if a > 0
        execute 'normal! '.c.'|'.a."\<C-a>"
    endif
    normal `<
endfunction

" true color
" set termguicolors

if &term =~# '^screen'
    let &t_8f = "\<Esc>[38;2;%lu;%lu;%lum"
    let &t_8b = "\<Esc>[48;2;%lu;%lu;%lum"
endif

set listchars=tab:→\ ,eol:↵,trail:·,extends:↷,precedes:↶

" patch-8.1.0360
set diffopt+=internal,algorithm:histogram
set completeopt+=noselect

set shellcmdflag=-ic

" diable buildin plugin
let g:loaded_gzip = 1
let g:loaded_tar = 1
let g:loaded_tarPlugin = 1
let g:loaded_zip = 1
let g:loaded_zipPlugin = 1
let g:loaded_getscript = 1
let g:loaded_getscriptPlugin = 1
let g:loaded_vimball = 1
let g:loaded_vimballPlugin = 1
let g:loaded_matchit = 1
let g:loaded_matchparen = 1
let g:loaded_2html_plugin = 1
let g:loaded_logiPat = 1
let g:loaded_rrhelper = 1
let g:loaded_netrw = 1
let g:loaded_netrwPlugin = 1
let g:loaded_netrwSettings = 1
let g:loaded_netrwFileHandlers = 1

function! s:DiffConfig()
    syntax off
    map n ]c
    map N [c
    silent! call lightline#disable()
    silent! CocCommand git.toggleGutters
    silent! CocDisable
    silent! set nocursorline nocursorcolumn
    silent! set signcolumn=no
    silent! nnoremap gq :qa<CR>
    silent! set shortmess+=I
endfunction

augroup VimDiff
    autocmd!
    autocmd VimEnter,FilterWritePre * if &diff | call s:DiffConfig() | endif
augroup END

" 
" function! SetColorScheme()
"     " check if tmux colorsheme is light or dark, and pick for vim accordingly
"     if system('tmux show-environment THEME')[0:9] == 'THEME=dark'
"         colorscheme zenburn
"     else
"         colorscheme seoul256-light
"     endif
" endfunction
"
"
function! SynGroup()
    let l:s = synID(line('.'), col('.'), 1)
    echo synIDattr(l:s, 'name') . ' -> ' . synIDattr(synIDtrans(l:s), 'name')
endfun

function! SynStack()
    if !exists("*synstack")
        return
    endif
    echo map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")')
endfunc

" Autocomplete parentheses and quotes 
inoremap ( ()<Left>
inoremap [ []<Left>
inoremap { {}<Left>
inoremap " ""<Left>
inoremap <expr> ' SmartQuote()

" Enhanced single quote handling (to avoid word completion) 
function! SmartQuote()
    let line = getline('.')
    let col = col('.') - 1
    let prev_char = col > 0 ? line[col-1] : ''
    let next_char = col < len(line) ? line[col] : ''

    " Skip if there are single quotes on the right 
    if next_char == "'"
        return "\<Right>"
	" Insert single quotes if the previous character is a letter (eg: don't）
    elseif prev_char =~ '\a'
        return "'"
    else
        return "''\<Left>"
    endif
endfunction

" Smart Backspace 
function! SmartBackspace() abort
    let col = col('.') - 1
    if col <= 0
        return "\<BS>"
    endif

    let line = getline('.')
    let prev_char = line[col - 1]
    let next_char = col < len(line) ? line[col] : ''

    if index(['()', '[]', '{}', '""', "''"], prev_char . next_char) != -1
        return "\<BS>\<Del>"
    endif
    return "\<BS>"
endfunction
inoremap <expr> <BS> SmartBackspace()

" Smart skip right symbol 
inoremap <expr> ) strpart(getline('.'), col('.')-1, 1) == ")" ? "\<Right>" : ")"
inoremap <expr> ] strpart(getline('.'), col('.')-1, 1) == "]" ? "\<Right>" : "]"
inoremap <expr> } strpart(getline('.'), col('.')-1, 1) == "}" ? "\<Right>" : "}"
inoremap /* /*  */<left><left><left>


